use askama::Template;
use axum::{
    extract::{  Json},
    http::StatusCode,
    response::{Html, IntoResponse},


};
use std::path::PathBuf;
use axum_messages::{Message, Messages};

use crate::users::AuthSession;
use crate::lolcate;

use serde::Deserialize;
use serde::Serialize;
use regex::{Regex};
use std::fs;
use std::io;

use std::str;
use bstr::io::BufReadExt;
use crate::logdb::write_log;
use axum::extract::ConnectInfo;

#[derive(Template)]
#[template(path = "ai-search.html")]
struct AITemplate<'a> {
    messages: Vec<Message>,
    username: &'a str,
}


pub mod get {
    use super::*;

    pub async fn ai_search(auth_session: AuthSession, 
                            messages: Messages, 
                            headers: axum::http::HeaderMap,
                            request: axum::extract::Request) -> impl IntoResponse {
        // 从请求中获取客户端IP
        let xff_header = headers.get("x-forwarded-for");
        let client_ip = match xff_header {
            Some(header) => header.to_str().unwrap_or("unknown"),
            None => {
                // 如果没有X-Forwarded-For头，尝试从连接中获取
                &match request.extensions().get::<std::net::SocketAddr>() {
                    Some(addr) => addr.to_string(),
                    None => "unknown".to_string(),
                }
            }
        };
        println!("client ip : {}", client_ip);

        match auth_session.user {
            Some(user) =>         Html(
                                        AITemplate {
                                            messages: messages.into_iter().collect(),
                                            username: &user.username,
                                        }
                                        .render()
                                        .unwrap(),
                                    ),
            None => Html(
                                        AITemplate {
                                            messages: messages.into_iter().collect(),
                                            username: "none",
                                        }
                                        .render()
                                        .unwrap(),
                                    ),
        }
    }  
}


// Define request and response structures
#[derive(Deserialize)]
pub struct SearchRequest {
    query: String,
}

#[derive(Serialize)]
pub struct SearchResult {
    #[serde(rename = "type")]
    file_type: String, // "directory" or "file"
    name: String,
    path: String,
}


pub mod post {
    use super::*;
    // Handle POST requests to /lolcate
    pub async fn handle_lolcate( ConnectInfo(addr): ConnectInfo<std::net::SocketAddr>,
                                Json(payload): Json<SearchRequest>) -> Result<Json<Vec<SearchResult>>, StatusCode> {
        // Validate query
        if payload.query.trim().is_empty() {
            return Err(StatusCode::BAD_REQUEST);
        }

        // Perform search (run blocking I/O on a thread pool)
        let results = tokio::task::spawn_blocking(move || {
            write_log( "admin".to_string(), "INFO".to_string(), addr.to_string(), "检索文件".to_string(),  format!("检索关键词是: {}", payload.query))
                .expect("Failed to write log");
            search_files(&payload.query)
        })
        .await
        .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

        Ok(Json(results))
    }
}

// File search implementation (runs on a thread pool)
fn search_files(query: &str) -> Vec<SearchResult> {
    let databases: Vec<String> = lolcate::database_names(lolcate::lolcate_config_path());
    let ignore_case = false;
    // 构建主查询的正则表达式
    let patterns_re = vec![lolcate::build_regex(query, ignore_case)];
    
    // 由于没有args参数，这里假设basename_pattern为空
    let bn_patterns_re: Vec<Regex> = Vec::new();
    
    // 类型过滤正则表达式（假设为空，表示不过滤类型）
    let types_re: Vec<Regex> = Vec::new();

    // 合并所有正则表达式 - 修复：先调用into_iter()将Vec转换为迭代器
    let all_patterns: Vec<Regex> = patterns_re.into_iter()
        .chain(bn_patterns_re.into_iter())
        .collect();

    // 执行数据库查询
    match lookup_databases(databases, &all_patterns, &types_re) {
        Ok(results) => results,
        Err(e) => {
            eprintln!("Error searching databases: {}", e);
            Vec::new() // 出错时返回空结果
        }
    }
}
fn lookup_databases(
    db_names: Vec<String>,
    patterns_re: &[Regex],
    types_re: &[Regex],
) -> std::io::Result<Vec<SearchResult>> {
    let mut all_results = Vec::new();
    
    for db_name in db_names {
        // 调用单个数据库的查找函数
        let db_results = lookup_database(&db_name, patterns_re, types_re)?;
        all_results.extend(db_results);
    }
    println!("lookup databases for files ");
    //for result in &all_results {
    //    println!("File Type: {}, Name: {}, Path: {}", 
    //            result.file_type, result.name, result.path);
    //}
    Ok(all_results)
}

fn lookup_database(
    db_name: &str,
    patterns_re: &[Regex],
    types_re: &[Regex],
) -> std::io::Result<Vec<SearchResult>> {
    let db_file = lolcate::db_fn(&db_name);
    
    // 检查数据库文件是否存在
    if !db_file.parent().unwrap().exists() {
        eprintln!(
            "Database {} doesn't exist. Perhaps you forgot to run lolcate --create {} ?",
            &db_name, &db_name
        );
        return Ok(Vec::new());
    }
    
    if !db_file.exists() {
        eprintln!(
            "Database {} is empty. Perhaps you forgot to run lolcate --update {} ?",
            &db_name, &db_name
        );
        return Ok(Vec::new());
    }
    
    // 打开并读取数据库文件
    let input_file = fs::File::open(db_file)?;
    let decoder = lz4::Decoder::new(input_file)?;
    let reader = io::BufReader::new(decoder);
    
    // 存储匹配结果
    let mut results = Vec::new();
    // 逐行处理数据库内容（使用字节流处理）

    let _ = reader.for_byte_line(|_line| {
        let line = str::from_utf8(_line).unwrap();
        if types_re.len() > 0 {
            if !types_re.iter().any(|re| re.is_match(&line)) {
                return Ok(true);
            }
        }
        if !patterns_re.iter().all(|re| re.is_match(&line)) {
            return Ok(true);
        }
        // 获取当前工作目录
        let current_dir = std::env::current_dir().expect("无法获取当前工作目录");
        println!("当前工作目录: {}", current_dir.display());

        // 获取命令行参数中的绝对路径
        let absolute_path = std::path::Path::new(&line);
        if !absolute_path.is_absolute() {
            eprintln!("错误: {} 不是绝对路径", absolute_path.display());
            std::process::exit(1);
        }
        println!("绝对路径: {}", absolute_path.display());

        // 计算相对路径
        let relative_path = get_relative_path(&current_dir, absolute_path);
        let mut rp = String::new();
        match relative_path {
            Some(path) => {
                rp = path.display().to_string();
                println!("相对路径: {}", path.display());
            },
            None => eprintln!("无法计算相对路径"),
        }
        #[allow(unused_must_use)]
        {
            results.push(SearchResult {
                file_type: "".to_string(),
                name: "".to_string(),
                path: rp,
            });
        }
        Ok(true)
    });
    
    Ok(results)
}

fn get_relative_path(base: &std::path::Path, path: &std::path::Path) -> Option<PathBuf> {
    // 确保两个路径都是绝对路径
    if !base.is_absolute() || !path.is_absolute() {
        return None;
    }

    // 尝试从路径中移除基础路径前缀
    path.strip_prefix(base)
        .map(PathBuf::from)
        .ok()
        .or_else(|| {
            // 如果前缀不匹配，尝试构建包含 ".." 的相对路径
            let mut rel_path = PathBuf::new();
            
            // 计算需要向上走多少级目录
            let mut parent = base.parent()?;
            
            while !path.starts_with(parent) {
                parent = parent.parent()?;
                rel_path.push("..");

            }
            
            // 添加从共同父目录到目标路径的剩余部分
            let remaining = path.strip_prefix(parent).ok()?;
            rel_path.push(remaining);
            
            Some(rel_path)
        })
}